//数字千分位分隔
export const format = (n: number): string => {
  let num: string = n.toString();
  let len: number = num.length;
  if (len <= 3) {
      return num;
  } else {
      let temp: string = '';
      let remainder: number = len % 3;
      if (remainder > 0) { 
          const matches = num.slice(remainder, len).match(/\d{3}/g);
          return num.slice(0, remainder) + ',' + (matches ? matches.join(',') : '') + temp;
      } else { 
          const matches = num.slice(0, len).match(/\d{3}/g);
          return (matches ? matches.join(',') : '') + temp; 
      }
  }
}

//全角转换为半角
export const toCDB = (str: string): string => {
  let result: string = "";
  for (let i = 0; i < str.length; i++) {
      const code = str.charCodeAt(i);
      if (code >= 65281 && code <= 65374) {
          result += String.fromCharCode(str.charCodeAt(i) - 65248);
      } else if (code == 12288) {
          result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32);
      } else {
          result += str.charAt(i);
      }
  }
  return result;
}

//半角转换为全角
export const toDBC = (str: string): string => {
  let result: string = "";
  for (let i = 0; i < str.length; i++) {
      const code = str.charCodeAt(i);
      if (code >= 33 && code <= 126) {
          result += String.fromCharCode(str.charCodeAt(i) + 65248);
      } else if (code == 32) {
          result += String.fromCharCode(str.charCodeAt(i) + 12288 - 32);
      } else {
          result += str.charAt(i);
      }
  }
  return result;
}

//数字转化为中文数字
export const intToChinese = (value: string): string => {
  const str: string = String(value);
  const len: number = str.length - 1;
  const idxs: string[] = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万', '十', '百', '千', '亿'];
  const num = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  return str.replace(/([1-9]|0+)/g, ($, $1, idx, full) => {
      let pos = 0;
      if ($1[0] !== '0') {
          pos = len - idx;
          if (idx == 0 && $1[0] == 1 && idxs[len - idx] == '十') {
              return idxs[len - idx];
          }
          return num[$1[0]] + idxs[len - idx];
      } else {
          let left = len - idx;
          let right = len - idx + $1.length;
          if (Math.floor(right / 4) - Math.floor(left / 4) > 0) {
              pos = left - left % 4;
          }
          if (pos) {
              return idxs[pos] + num[$1[0]];
          } else if (idx + $1.length >= len) {
              return '';
          } else {
              return num[$1[0]];
          }
      }
  });
}

//存储sessionStorage
export const sessionStorageSet = (key: string, value: any): void => {
  if (!key) return;
  if (typeof value !== 'string') {
      value = JSON.stringify(value);
  }
  window.sessionStorage.setItem(key, value);
};

//获取sessionStorage
export const sessionStorageGet = (key: string): string | null => {
  if (!key) return null;
  return window.sessionStorage.getItem(key);
};

//删除sessionStorage
export const sessionStorageRemove = (key: string): void => {
  if (!key) return;
  window.sessionStorage.removeItem(key);
};

//删除cookie
export const delCookie = (key: string): void => {
  document.cookie = `${encodeURIComponent(key)}=;expires=${new Date()}`;
};

//校验是否为中国大陆的邮政编码
export const isPostCode = (value: string): boolean => {
  return /^[1-9][0-9]{5}$/.test(value.toString());
}

//校验是否为IPv6地址
export const isIPv6 = (str: string): boolean => {
  const ipv6Pattern = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;

  return ipv6Pattern.test(str);
}

//校验是否为邮箱地址
export const isEmail = (value: string): boolean => {
  return /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value);
}

//校验是否为中国大陆手机号
export const isTel = (value: number): boolean => {
  return /^1[3,4,5,6,7,8,9][0-9]{9}$/.test(value.toString());
}

//校验是否包含emoji表情
export const isEmojiCharacter = (value: any): boolean => {
  value = String(value);
  for (let i = 0; i < value.length; i++) {
      const hs = value.charCodeAt(i);
      if (0xd800 <= hs && hs <= 0xdbff) {
          if (value.length > 1) {
              const ls = value.charCodeAt(i + 1);
              const uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
              if (0x1d000 <= uc && uc <= 0x1f77f) {
                  return true;
              }
          }
      } else if (value.length > 1) {
          const ls = value.charCodeAt(i + 1);
          if (ls == 0x20e3) {
              return true;
          }
      } else {
          if (0x2100 <= hs && hs <= 0x27ff) {
              return true;
          } else if (0x2B05 <= hs && hs <= 0x2b07) {
              return true;
          } else if (0x2934 <= hs && hs <= 0x2935) {
              return true;
          } else if (0x3297 <= hs && hs <= 0x3299) {
              return true;
          } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030
              || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b
              || hs == 0x2b50) {
              return true;
          }
      }
  }
  return false;
}

//检测URL是否有效
export const getUrlState = (URL: string): boolean => {
  let xmlhttp = new ActiveXObject("microsoft.xmlhttp");
  xmlhttp.Open("GET", URL, false);
  try {
      xmlhttp.Send();
  } catch (e) {
  } finally {
      let result = xmlhttp.responseText;
      if (result) {
          if (xmlhttp.Status == 200) {
              return true;
          } else {
              return false;
          }
      } else {
          return false;
      }
  }
}

//修改URL中的参数
export const replaceParamVal = (paramName: string, replaceWith: string): string => {
  const oUrl = location.href.toString();
  const re = new RegExp('(' + paramName + '=)([^&]*)', 'gi');
  location.href = oUrl.replace(re, paramName + '=' + replaceWith);
  return location.href;
}

//删除URL中指定参数
export const funcUrlDel = (name: string): string => {
  const baseUrl = location.origin + location.pathname + "?";
  const query = location.search.substr(1);
  if (query.indexOf(name) > -1) {
      const obj: { [key: string]: string } = {};
      const pairs = query.split("&");
      for (const pair of pairs) {
          const [key, value] = pair.split("=");
          obj[key] = value;
      }
      delete obj[name];
      return baseUrl + JSON.stringify(obj).replace(/[\"\{\}]/g, "").replace(/\:/g, "=").replace(/\,/g, "&");
  }
  return baseUrl + query;
}

//判断是否是苹果还是安卓移动设备
export const isAppleMobileDevice = (): boolean => {
  let reg = /iphone|ipod|ipad|Macintosh/i;
  return reg.test(navigator.userAgent.toLowerCase());
}

//判断是否是安卓移动设备
export const isAndroidMobileDevice = (): boolean => {
  return /android/i.test(navigator.userAgent.toLowerCase());
}

//判断是否是微信/QQ内置浏览器
export const browser = (): string | boolean => {
  const ua = navigator.userAgent.toLowerCase();
  if (ua.match(/MicroMessenger/i)) {
      return "weixin";
  } else if (ua.match(/QQ/i)) {
      return "QQ";
  }
  return false;
}

//浏览器型号和版本
export const getExplorerInfo = (): { type: string, version: number } => {
  let t = navigator.userAgent.toLowerCase();
  const msieMatch = t.match(/msie ([\d]+)/);
  const tridentMatch = t.match(/trident\/.+?rv:(([\d.]+))/);
  
  if (t.indexOf("msie") >= 0 && msieMatch) { // IE < 11
    return {
      type: "IE",
      version: Number(msieMatch[1])
    };
  } else if (tridentMatch) { // IE 11
    return {
      type: "IE",
      version: 11
    };
  } else if (t.indexOf("edge") >= 0) {
    return {
      type: "Edge",
      version: Number(t.match(/edge\/([\d]+)/)?.[1] || -1)
    };
  } else if (t.indexOf("firefox") >= 0) {
    return {
      type: "Firefox",
      version: Number(t.match(/firefox\/([\d]+)/)?.[1] || -1)
    };
  } else if (t.indexOf("chrome") >= 0) {
    return {
      type: "Chrome",
      version: Number(t.match(/chrome\/([\d]+)/)?.[1] || -1)
    };
  } else if (t.indexOf("opera") >= 0) {
    return {
      type: "Opera",
      version: Number(t.match(/opera.([\d]+)/)?.[1] || -1)
    };
  } else if (t.indexOf("safari") >= 0) {
    return {
      type: "Safari",
      version: Number(t.match(/version\/([\d]+)/)?.[1] || -1)
    };
  } else {
    return {
      type: "Unknown",
      version: -1
    };
  }
}

//滚动到页面底部
export const scrollToBottom = (): void => {
  window.scrollTo(0, document.documentElement.clientHeight);
}

//滚动到指定元素区域
export const smoothScroll = (element: string): void => {
  document.querySelector(element)?.scrollIntoView({
      behavior: 'smooth'
  });
};

//获取可视窗口宽度
export const getPageViewWidth = (): number => {
  return (document.compatMode == "BackCompat" ? document.body : document.documentElement).clientWidth;
}

//打开浏览器全屏
export const toFullScreen = (): void => {
  let element = document.body;
  if (element.requestFullscreen) {
      element.requestFullscreen()
  } else if (element.requestFullscreen) {
      element.requestFullscreen()
  } else if (element.requestFullscreen) {
      element.requestFullscreen()
  } else if (element.requestFullscreen) {
      element.requestFullscreen()
  }
}

//退出浏览器全屏
export const exitFullscreen = (): void => {
  const doc = document as Document & {
      msExitFullscreen?: () => Promise<void>;
      mozCancelFullScreen?: () => Promise<void>;
      webkitExitFullscreen?: () => Promise<void>;
  };
  
  if (doc.exitFullscreen) {
      doc.exitFullscreen();
  } else if (doc.msExitFullscreen) {
      doc.msExitFullscreen();
  } else if (doc.mozCancelFullScreen) {
      doc.mozCancelFullScreen();
  } else if (doc.webkitExitFullscreen) {
      doc.webkitExitFullscreen();
  }
};
//当前时间
export const nowTime = (): string => {
  const now = new Date();
  const year = now.getFullYear();
  const month = now.getMonth();
  const date = now.getDate() >= 10 ? now.getDate() : ('0' + now.getDate());
  const hour = now.getHours() >= 10 ? now.getHours() : ('0' + now.getHours());
  const miu = now.getMinutes() >= 10 ? now.getMinutes() : ('0' + now.getMinutes());
  const sec = now.getSeconds() >= 10 ? now.getSeconds() : ('0' + now.getSeconds());
  return year + "年" + (month + 1) + "月" + date + "日 " + hour + ":" + miu + ":" + sec;
}

//阻止冒泡事件
export const stopPropagation = (e: Event): void => {
  e = e || window.event;
  if (e.stopPropagation) {
      e.stopPropagation();
  } else {
      (e as any).cancelBubble = true; 
  }
}

//数据类型判断
export const getType = (value: any): string => {
  if (value === null) {
      return value + "";
  }

  if (typeof value === "object") {
      let valueClass = Object.prototype.toString.call(value),
          type = valueClass.split(" ")[1].split("");
      type.pop();
      return type.join("").toLowerCase();
  } else {
      return typeof value;
  }
}